home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #2 / Amiga Plus CD - 2004 - No. 02.iso / AmigaPlus / Tools / Anwendungen / glmatrix / source / yarandom.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-01-31  |  4.2 KB  |  128 lines

  1. /* yarandom.c -- Yet Another Random Number Generator.
  2.  * Copyright (c) 1997, 1998, 2003 by Jamie Zawinski <jwz@jwz.org>
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided that
  6.  * the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation.  No representations are made about the suitability of this
  9.  * software for any purpose.  It is provided "as is" without express or
  10.  * implied warranty.
  11.  */
  12.  
  13. /* The unportable mess that is rand(), random(), drand48() and friends led me
  14.    to ask Phil Karlton <karlton@netscape.com> what the Right Thing to Do was.
  15.    He responded with this.  It is non-cryptographically secure, reasonably
  16.    random (more so than anything that is in any C library), and very fast.
  17.  
  18.    I don't understand how it works at all, but he says "look at Knuth,
  19.    Vol. 2 (original edition), page 26, Algorithm A.  In this case n=55,
  20.    k=20 and m=2^32."
  21.  
  22.    So there you have it.
  23.  
  24.    ---------------------------
  25.    Note: xlockmore 4.03a10 uses this very simple RNG:
  26.  
  27.     if ((seed = seed % 44488 * 48271 - seed / 44488 * 3399) < 0)
  28.       seed += 2147483647;
  29.     return seed-1;
  30.  
  31.    of which it says
  32.  
  33.     ``Dr. Park's algorithm published in the Oct. '88 ACM  "Random Number
  34.       Generators: Good Ones Are Hard To Find" His version available at
  35.       ftp://cs.wm.edu/pub/rngs.tar Present form by many authors.''
  36.  
  37.    Karlton says: ``the usual problem with that kind of RNG turns out to
  38.    be unexepected short cycles for some word lengths.''
  39.  
  40.    Karlton's RNG is faster, since it does three adds and two stores, while the
  41.    xlockmore RNG does two multiplies, two divides, three adds, and one store.
  42.  
  43.    Compiler optimizations make a big difference here:
  44.        gcc -O:     difference is 1.2x.
  45.        gcc -O2:    difference is 1.4x.
  46.        gcc -O3:    difference is 1.5x.
  47.        SGI cc -O:  difference is 2.4x.
  48.        SGI cc -O2: difference is 2.4x.
  49.        SGI cc -O3: difference is 5.1x.
  50.    Irix 6.2; Indy r5k; SGI cc version 6; gcc version 2.7.2.1.
  51.  */
  52.  
  53. #define HAVE_UNISTD_H
  54. #define GETTIMEOFDAY_TWO_ARGS
  55.  
  56. #ifdef HAVE_CONFIG_H
  57. # include "config.h"
  58. #endif
  59.  
  60. #ifdef HAVE_UNISTD_H
  61. # include <unistd.h>  /* for getpid() */
  62. #endif
  63. #include <sys/time.h> /* for gettimeofday() */
  64.  
  65. /*#include "yarandom.h" */
  66. # undef ya_rand_init
  67.  
  68.  
  69. /* The following 'random' numbers are taken from CRC, 18th Edition, page 622.
  70.    Each array element was taken from the corresponding line in the table,
  71.    except that a[0] was from line 100. 8s and 9s in the table were simply
  72.    skipped. The high order digit was taken mod 4.
  73.  */
  74. #define VectorSize 55
  75. static unsigned int a[VectorSize] = {
  76.  035340171546, 010401501101, 022364657325, 024130436022, 002167303062, /*  5 */
  77.  037570375137, 037210607110, 016272055420, 023011770546, 017143426366, /* 10 */
  78.  014753657433, 021657231332, 023553406142, 004236526362, 010365611275, /* 14 */
  79.  007117336710, 011051276551, 002362132524, 001011540233, 012162531646, /* 20 */
  80.  007056762337, 006631245521, 014164542224, 032633236305, 023342700176, /* 25 */
  81.  002433062234, 015257225043, 026762051606, 000742573230, 005366042132, /* 30 */
  82.  012126416411, 000520471171, 000725646277, 020116577576, 025765742604, /* 35 */
  83.  007633473735, 015674255275, 017555634041, 006503154145, 021576344247, /* 40 */
  84.  014577627653, 002707523333, 034146376720, 030060227734, 013765414060, /* 45 */
  85.  036072251540, 007255221037, 024364674123, 006200353166, 010126373326, /* 50 */
  86.  015664104320, 016401041535, 016215305520, 033115351014, 017411670323  /* 55 */
  87. };
  88.  
  89. static int i1 = 15, i2 = 37;
  90.  
  91. unsigned int
  92. ya_random (void)
  93. {
  94.   register int ret = a[i1] + a[i2];
  95.   a[i1] = ret;
  96.   if (++i1 >= VectorSize) i1 = 0;
  97.   if (++i2 >= VectorSize) i2 = 0;
  98.   return ret;
  99. }
  100.  
  101. void ya_rand_init(unsigned int seed)
  102. {
  103.   int i;
  104.   if (seed == 0)
  105.     {
  106.       struct timeval tp;
  107. #ifdef GETTIMEOFDAY_TWO_ARGS
  108.       struct timezone tzp;
  109.       gettimeofday(&tp, &tzp);
  110.  
  111. #else
  112.       gettimeofday(&tp);
  113. #endif
  114.       /* ignore overflow */
  115.       seed = (999*tp.tv_sec) + (1001*tp.tv_usec) + (1003 * getpid());
  116.     }
  117.  
  118.   a[0] += seed;
  119.   for (i = 1; i < VectorSize; i++)
  120.     {
  121.       seed = a[i-1]*1001 + seed*999;
  122.       a[i] += seed;
  123.     }
  124.  
  125.   i1 = a[0] % VectorSize;
  126.   i2 = (i1 + 024) % VectorSize;
  127. }
  128.